//
// Created by haoy on 2017/6/20.
//

#include <xrtc_endpoint.h>
#include "rtp/rtp_packet.hpp"

#include "xcutil.h"

RtpPacket::RtpPacket() {}

int RtpPacket::read(const uint8_t* data, const int size, rtc_codecs_t* codecs) {
    if (size > MAX_BUF) {
        return 0;
    }

    memcpy(buffer, data, size);
    buffer_size = size;

    auto hdr_size = header.read(data, size);
    if (hdr_size == 0) {
        return 0;
    }

    if (header.p == 1) {
        padding_size = data[size - 1];
    } else {
        padding_size = 0;
    }

    csrc = buffer+12;
    csrc_len = header.cc * 4;

    ext = csrc+csrc_len;
    if (header.x == 1) {
        auto l = be_get_u16(ext+2);
        ext_len = (l+1) * 4;
    } else {
        ext_len = 0;
    }

    payload = ext + ext_len;
    payload_size = size - hdr_size - csrc_len - ext_len - padding_size;

    rtc_codec_t* codec = rtc_codecs_find_by_pt(codecs, header.pt);
    if (!codec) {
        return 0;
    }

    codec_id = codec->id;

    if (codec_id == rtc_codec_id_ulpfec) {
        // payload = [fec_header + fec_level_header + fec_payload]
        fec.read(payload, payload_size);
    }
    return size;
}

int RtpPacket::write(uint8_t* data, const int size, rtc_codecs_t* codecs) const {
    if (size < this->size()) {
        return 0;
    }
    auto new_header = header;
    rtc_codec_t* codec = rtc_codecs_find_by_id(codecs, codec_id);
    if (!codec) {
        return 0;
    }
    new_header.pt = codec->pt;
    auto hdr_write = new_header.write(data, size);
    if (hdr_write == 0) {
        return 0;
    }
    memcpy(data + hdr_write, csrc, csrc_len);
    memcpy(data + hdr_write + csrc_len, ext, ext_len);
    memcpy(data + hdr_write + csrc_len + ext_len, payload, payload_size);
    return csrc_len + ext_len + payload_size;
}

int RtpPacket::size() const {
    return buffer_size;
}
